package com.fy.fyspace.common.aop;

import com.fy.fyspace.common.annotation.GlobalInterceptor;
import com.fy.fyspace.ex.ConditionException;
import com.fy.fyspace.ex.handler.ExceptionHandler;
import com.fy.fyspace.model.vo.user.UserSessionVO;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Objects;

import static com.fy.fyspace.constant.KeysConstant.LOGIN_SESSION_KEY;
import static com.fy.fyspace.constant.ResultMessageConstant.LOGIN_EXPIRED;
import static com.fy.fyspace.constant.ResultMessageConstant.NO_AUTH_ERROR;

/**
 * 全局操作拦截器
 * 用于处理接口的登录验证、参数校验等通用操作
 */
@Component("operationAspect")
@Aspect
@Slf4j
public class GlobalOperationAspect {
    private static final Logger logger = LoggerFactory.getLogger(GlobalOperationAspect.class);

    /**
     * 定义切点，拦截带有GlobalInterceptor注解的方法
     */
    @Pointcut("@annotation(com.fy.fyspace.common.annotation.GlobalInterceptor)")
    private void requestInterceptor() {
    }

    /**
     * 前置通知，进行登录检查和参数校验
     */
    @Before("requestInterceptor()")
    public void interceptorDo(JoinPoint point) throws ConditionException {
        try {
            Object target = point.getTarget();
            String methodName = point.getSignature().getName();
            Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
            Method method = target.getClass().getMethod(methodName, parameterTypes);
            GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);

            if (null == interceptor) {
                return;
            }

            // 登录校验
            if (interceptor.checkLogin() || interceptor.checkAdmin()) {
                checkLogin(interceptor.checkAdmin());
            }

        } catch (ConditionException e) {
            logger.error("全局拦截器异常", e);
            throw e;
        } catch (Exception e) {
            logger.error("全局拦截器异常", e);
        }
    }

    /**登录状态检查
     *
     * @param checkAdmin
     */

    private void checkLogin(Boolean checkAdmin) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        HttpSession session = request.getSession();
        UserSessionVO userSessionVO = (UserSessionVO) session.getAttribute(LOGIN_SESSION_KEY);

        log.info("UserSessionVO:{}", userSessionVO);
        ExceptionHandler.throwIf(Objects.equals(userSessionVO, null), LOGIN_EXPIRED);
        ExceptionHandler.throwIf(checkAdmin && !"admin".equals(userSessionVO.getUserRole()),
                NO_AUTH_ERROR);
    }
}